
function CanvasLayer(name)
{
  this.element = $(name);
  
  if(this.element.getContext)
  {
    this.context = this.element.getContext('2d');
  } else {
    throw new Error('Canvas ('+name+'): Cannot get Context');
  }
  
  this.size = $V(this.element.width,this.element.height);
  
  this.matrix = new Matrix33();
  this.matrixStack = Array();
}

CanvasLayer.prototype.drawLine = function (style, point1, point2)
{
  style.setup(this.context);
  
  this.context.beginPath();
   
  this.context.moveTo(point1.x,point1.y);
  this.context.lineTo(point2.x,point2.y);  
    
  style.use(this.context);
  
  this.context.closePath();  
}

CanvasLayer.prototype.drawRect = function (style, point1, point2)
{   
  style.setup(this.context);
  
  this.context.beginPath();

  var widthHeight = point2.sub(point1);
  this.context.rect(point1.x,point1.y,widthHeight.x,widthHeight.y);
  
  style.use(this.context);
  
  this.context.closePath();
}

CanvasLayer.prototype.clearRect = function (point1,point2)
{
  var widthHeight = point2.sub(point1);
  this.context.clearRect(point1.x,point1.y,widthHeight.x,widthHeight.y);
}

CanvasLayer.prototype.drawImage = function (image, point1, point2)
{
  var widthHeight = point2.sub(point1);
  this.context.drawImage(image,point1.x,point1.y,widthHeight.x,widthHeight.y);  
}

CanvasLayer.prototype.drawText = function (style, text, point)
{
  if(!style.is('Font'))
    throw new Error('Not font style');
    
  style.setup(this.context);
    
  if(!style.is('Line'))
    this.context.fillText(text,point.x,point.y);
  else
    this.context.strokeText(text,point.x,point.y);  
}

CanvasLayer.prototype.save = function ()
{
  //this.context.save();
  this.matrixStack.push(this.matrix.clone());
}

CanvasLayer.prototype.restore = function ()
{
  //this.context.restore();
  this.matrix = this.matrixStack.pop();
}

CanvasLayer.prototype.translate = function (point)
{
  //this.context.translate(point.x,point.y);
  var m = new Matrix33();
  this.matrix = this.matrix.mul(m.translate(point))
}

CanvasLayer.prototype.rotate = function (angle)
{
  //this.context.rotate(angle);
  var m = new Matrix33();
  this.matrix = this.matrix.mul(m.rotate(angle));
}

CanvasLayer.prototype.scale = function (scale)
{
  //this.context.scale(scale.x,scale.y);
  var m = new Matrix33();
  this.matrix = this.matrix.mul(m.scale(scale));  
}

CanvasLayer.prototype.setTransformMatrix = function (m11,m12,m21,m22,x,y)
{
  //this.context.setTransform(m11,m12,m21,m22,x,y);
  this.matrix.specify([m11,m21,x,m12,m22,y,0,0,1]);
}

CanvasLayer.prototype.loadMatrix = function ()
{
  this.context.setTransform(this.matrix._00,this.matrix._01,this.matrix._10,this.matrix._11,this.matrix._20,this.matrix._21);
}


CanvasLayer.prototype.getPixel = function (point)
{
  var pixel = this.context.getImageData(point.x,point.y,1,1).data;
  return rgb(pixel[0],pixel[1],pixel[2],pixel[3]);
}

CanvasLayer.prototype.getImageData = function (point1,point2)
{
  var widthHeight = point2.sub(point1);
  return this.context.getImageData(point1.x,point1.y,widthHeight.x,widthHeight.y);
}

CanvasLayer.prototype.putImageData = function (data, point)
{  
  this.context.putImageData(data,point.x,point.y);
}

function BaseLayers(coordinateConversionCallback)
{
  this.layers = Array();
  this.coordinateConversionCallback = coordinateConversionCallback;
}

BaseLayers.prototype.addLayer = function (name)
{
  this.layers.push(new CanvasLayer(name,this.coordinateConversionCallback));
}

BaseLayers.prototype.getLayer = function (i)
{
  return this.layers[i];
}

BaseLayers.prototype.isTopLayer = function (layer)
{
  return layer == this.layers.length - 1;
}

BaseLayers.prototype.getTopLayer = function ()
{
  return this.layers[this.layers.length - 1];
}